//自定义指令集合
import { useNavTabs } from "@/store/navTabs";
import { App, nextTick } from "vue";
import horizontalScroll from "@/utils/horizontalScroll";
// createRouter函数 会返回一个router实例
import router from "@/router/index";
export function directives(app: App) {
  // 鉴权指令
  authDirective(app);
  // 拖动指令;
  dragDirective(app);
  // 缩放指令
  zoomDirective(app);
  // 点击后自动失焦指令
  blurDirective(app);
  // 表格横向拖动指令
  tableLateralDragDirective(app);
  // setupThrottleDriective(app);
}

/**
 * 点击后自动失焦指令
 * @description v-blur
 */
function blurDirective(app: App) {
  app.directive("blur", {
    mounted(el) {
      el.addEventListener("focus", () => {
        el.blur();
      });
    },
  });
}

/**
 * 表格横向滚动指令
 * @description v-table-lateral-drag
 */
function tableLateralDragDirective(app: App) {
  app.directive("tableLateralDrag", {
    created(el) {
      new horizontalScroll(
        el.querySelector(
          ".el-table__body-wrapper .el-scrollbar .el-scrollbar__wrap"
        )
      );
    },
  });
}

/**
 * 页面按钮鉴权指令
 * @description v-auth="'name'"，name可以为：index,add,edit,del,...
 *
 * <div v-example:foo.bar="baz">的binding参数为
 * {
 * arg: 'foo',
 * modifiers: { bar: true },
 * value:  `baz` 的值
 * oldValue:  上一次更新时 `baz` 的值
 * }
 *
 * 菜单管理页面router.currentRoute.value.path="/admin/SysM/menu"
 *
 * 权限节点 navTabs.state.authNode 为new Map().set('当前页面路由（/admin/DeviceM/access）',[/admin/DeviceM/access/index,...])
 */
function authDirective(app: App) {
  app.directive("auth", {
    mounted(el, binding) {
      if (!binding.value) return false;
      //从navTabs中获取权限节点数据
      const navTabs = useNavTabs();
      let Nodes = JSON.parse(JSON.stringify(navTabs.state.authNodes));
      // console.log(
      //   "router",
      //   router.currentRoute.value.path,
      //   "Nodes",
      //   Nodes,
      //   "navTabs.state.authNode",
      //   navTabs.state.authNode,
      //   "binding.value",
      //   binding.value,
      //   router.currentRoute.value.path + "/" + binding.value,
      //   Nodes.includes(router.currentRoute.value.path + "/" + binding.value)
      // );

      if (navTabs.state.authNode.get("/admin/")![0] === "*:*:*") {
        return;
      }
      if (binding.value === "edit") {
        if (
          (!Nodes.includes("/admin/system/evenhandle/list") ||
            !Nodes.includes("/admin/system/evenhandle/add")) &&
          router.currentRoute.value.path === "/admin/EquipM/eventHandle"
        ) {
          el.parentNode.removeChild(el);
          return;
        }
      }
      //针对企业详情页设备列表的维修记录按钮
      if (
        !Nodes.includes(router.currentRoute.value.path + "/" + binding.value)
      ) {
        el.parentNode.removeChild(el);
      }
    },
  });
}

/**
 * @desc 函数节流
 * @param fn 函数
 * @param time 延迟执行毫秒数
 * @param type 1 表时间戳版，2 表定时器版
 */
// function throttleELfun(el: HTMLElement, throttleTime = 200) {
//   let timer: null | NodeJS.Timeout = null;
//   el.addEventListener(
//     "click",
//     (event: Event) => {
//       if (!timer) {
//         (timer as any) = window.setTimeout(() => {
//           timer = null;
//         }, throttleTime);
//       } else {
//         event?.stopImmediatePropagation();
//       }
//     },
//     true
//   );
// }

// function setupThrottleDriective(app: App) {
//   app.directive("throttle", {
//     beforeMount(el, bingding) {
//       throttleELfun(el, bingding.value);
//     },
//   });
// }

/**
 * 缩放指令
 * @description v-zoom="[domEl]"
 * @description domEl=要开启缩放的元素
 */
function zoomDirective(app: App) {
  app.directive("zoom", {
    mounted(el, binding) {
      if (!binding.value) return false;

      nextTick(() => {
        const zoomDom = document.querySelector(binding.value) as HTMLElement;
        const zoomhandleEl = document.createElement("div");
        zoomhandleEl.className = "zoom-handle";
        zoomhandleEl.onmouseenter = () => {
          zoomhandleEl.onmousedown = (e: MouseEvent) => {
            const x = e.clientX;
            const y = e.clientY;
            const zoomDomWidth = zoomDom.offsetWidth;
            const zoomDomHeight = zoomDom.offsetHeight;
            document.onmousemove = (e: MouseEvent) => {
              e.preventDefault(); // 移动时禁用默认事件
              const w = zoomDomWidth + (e.clientX - x) * 2;
              const h = zoomDomHeight + (e.clientY - y);

              zoomDom.style.width = `${w}px`;
              zoomDom.style.height = `${h}px`;
            };

            document.onmouseup = function () {
              document.onmousemove = null;
              document.onmouseup = null;
            };
          };
        };

        zoomDom.appendChild(zoomhandleEl);
      });
    },
  });
}

/**
 * 拖动指令
 * @description v-drag="[domEl,handleEl]"
 * @description domEl=被拖动的元素，handleEl=在此元素内可以拖动`dom`
 */
interface downReturn {
  [key: string]: number;
}
function dragDirective(app: App) {
  app.directive("drag", {
    mounted(el, binding) {
      if (!binding.value) return false;

      const dragDom = document.querySelector(binding.value[0]) as HTMLElement;
      const dragHandle = document.querySelector(
        binding.value[1]
      ) as HTMLElement;

      if (!dragHandle || !dragDom) {
        return false;
      }

      dragHandle.onmouseover = () => (dragHandle.style.cursor = `move`);

      function down(e: MouseEvent | TouchEvent, type: string): downReturn {
        // 鼠标按下，计算当前元素距离可视区的距离
        const disX =
          type === "pc"
            ? (e as MouseEvent).clientX - dragHandle.offsetLeft
            : (e as TouchEvent).touches[0].clientX - dragHandle.offsetLeft;
        const disY =
          type === "pc"
            ? (e as MouseEvent).clientY - dragHandle.offsetTop
            : (e as TouchEvent).touches[0].clientY - dragHandle.offsetTop;

        // body宽度
        const screenWidth = document.body.clientWidth;
        const screenHeight =
          document.body.clientHeight || document.documentElement.clientHeight;

        // 被拖动元素宽度
        const dragDomWidth = dragDom.offsetWidth;
        // 被拖动元素高度
        const dragDomheight = dragDom.offsetHeight;

        // 拖动限位
        const minDragDomLeft = dragDom.offsetLeft;
        const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
        const minDragDomTop = dragDom.offsetTop;
        const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;

        // 获取到的值带px 正则匹配替换
        let styL: string | number = getComputedStyle(dragDom).left;
        let styT: string | number = getComputedStyle(dragDom).top;
        styL = +styL.replace(/\px/g, "");
        styT = +styT.replace(/\px/g, "");

        return {
          disX,
          disY,
          minDragDomLeft,
          maxDragDomLeft,
          minDragDomTop,
          maxDragDomTop,
          styL,
          styT,
        };
      }

      function move(e: MouseEvent | TouchEvent, type: string, obj: downReturn) {
        const {
          disX,
          disY,
          minDragDomLeft,
          maxDragDomLeft,
          minDragDomTop,
          maxDragDomTop,
          styL,
          styT,
        } = obj;

        // 通过事件委托，计算移动的距离
        let left =
          type === "pc"
            ? (e as MouseEvent).clientX - disX
            : (e as TouchEvent).touches[0].clientX - disX;
        let top =
          type === "pc"
            ? (e as MouseEvent).clientY - disY
            : (e as TouchEvent).touches[0].clientY - disY;

        // 边界处理
        if (-left > minDragDomLeft) {
          left = -minDragDomLeft;
        } else if (left > maxDragDomLeft) {
          left = maxDragDomLeft;
        }

        if (-top > minDragDomTop) {
          top = -minDragDomTop;
        } else if (top > maxDragDomTop) {
          top = maxDragDomTop;
        }

        // 移动当前元素
        dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
      }

      dragHandle.onmousedown = (e) => {
        const obj = down(e, "pc");
        document.onmousemove = (e) => {
          move(e, "pc", obj);
        };
        document.onmouseup = () => {
          document.onmousemove = null;
          document.onmouseup = null;
        };
      };
      dragHandle.ontouchstart = (e) => {
        const obj = down(e, "app");
        document.ontouchmove = (e) => {
          move(e, "app", obj);
        };
        document.ontouchend = () => {
          document.ontouchmove = null;
          document.ontouchend = null;
        };
      };
    },
  });
}
